package cn.zk.commom.tcp.obd;

import org.springframework.stereotype.Component;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;

@Component
public class ObdInfo {
    public final  int        mMsgId;                  //消息ID
    public final  String     mPhoneNumber;           //手机号
    public final  int        mMsgSerialNumber;       //消息流水号
    public final ArrayList<Position> mPosition;      //位置信息

    //
    public ObdInfo(byte[] data){
        mMsgId = (int)ByteArrayToLong(data, 1 ,2);
        int len = (int)ByteArrayToLong(data, 3 ,2);

        //手机号
        StringBuilder str1 = new StringBuilder();
        if (data.length>11){
            for (int i = 5; i < 11; ++i) {
                str1.append(String.format("%02x", data[i]));
            }
        }
        mPhoneNumber = str1.toString();
        mMsgSerialNumber = (int)ByteArrayToLong(data, 11, 2);

        //解析位置信息
        ByteArrayOutputStream _tep = new ByteArrayOutputStream();

        if (data.length>13){
            _tep.write(data, 13, len);
        }
        ArrayList<Position> _positionArray = new ArrayList<>();
        if(mMsgId == 0x0200) {
            mPosition = AnalyseByteData_0200(_tep.toByteArray());
        } else if(mMsgId == 0x0704)  {
            mPosition = AnalyseByteData_0704(_tep.toByteArray());
        } else if(mMsgId == 0x0900) {
            mPosition = AnalyseByteData_0704(_tep.toByteArray());
        } else {
            mPosition = new ArrayList<>();
        }
    }

    /***
     * 解析 msgID = 0x0200
     * @param data 完整的数据帧，包含头尾0x7e
     * @return 返回位置信息
     */
    private ArrayList<Position> AnalyseByteData_0200(byte[] data) {
        ArrayList<Position> ret = new ArrayList<>();
        Position _pos = new Position(data);
        if(_pos.mIsValid) {
            ret.add(_pos);
        }
        return ret;
    }

    /***
     * 解析 msgID = 0x0704
     * @param data 完整的数据帧，包含头尾0x7e
     * @return 返回位置信息
     */
    private ArrayList<Position> AnalyseByteData_0704(byte[] data) {
        ArrayList<Position> ret = new ArrayList<>();
        ArrayList<ByteArrayOutputStream>  _addMsg = AdditionalMsgDataSplitting(data);
        for(ByteArrayOutputStream var : _addMsg)
        {
            Position _pos = new Position(var.toByteArray());
            if(_pos.mIsValid) {
                ret.add(_pos);
            }
        }
        return ret;
    }

    /***
     * 解析 msgID = 0x0900
     * @param data 完整的数据帧，包含头尾0x7e
     * @return 返回位置信息
     */
    private ArrayList<Position> AnalyseByteData_0900(byte[] data) {
        ArrayList<Position> ret = new ArrayList<>();
//        ArrayList<ByteArrayOutputStream>  _addMsg = AdditionalMsgDataSplitting(data);
//        for(ByteArrayOutputStream var : _addMsg)
//        {
//            Position _pos = new Position(var.toByteArray());
//            if(_pos.mIsValid) {
//                ret.add(_pos);
//            }
//        }
        return ret;
    }

    /***
     * 拆分批量汇报数据
     * @param data 批量汇报数据
     * @return
     */
    private ArrayList<ByteArrayOutputStream> AdditionalMsgDataSplitting(byte[] data) {
        ArrayList<ByteArrayOutputStream> ret = new ArrayList<>();

        int sub_index = 3;
        while(true)
        {
            if(sub_index + 2 > data.length )
                break;

            //0:子类型; 1:子类型长度
            int sub_len  = (int)ByteArrayToLong(data, sub_index, 2);   //子长度
            int new_index = sub_index + sub_len + 2;

            if(new_index > data.length)
                break;

            ByteArrayOutputStream _tep = new ByteArrayOutputStream();
            _tep.write(data, sub_index + 2, sub_len);
            ret.add(_tep);

            sub_index = new_index;
        }

        return  ret;
    }
    public static long ByteArrayToLong(byte[] data, int index ,int len) {
        if(index < 0 || len <= 0 || index >= data.length || len + index > data.length)
            return  0;

        //
        long ret = (data[index] & 0xff);
        for(int i = 1; i < len; ++i)
        {
            ret = (ret << 8)  + (data[i + index] & 0xff);
        }

        return  ret;
    }
}
